
package com.job.dao.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;

import com.job.dao.BaseDao;

@Component(value="baseDao")
public class BaseDaoSupport extends HibernateDaoSupport implements BaseDao {
	
	@Resource(name="sessionFactory")
	public void setHibernateTemplateSessionFactory(SessionFactory sessionFactory){
		super.setSessionFactory(sessionFactory);
	}
	@Override
	public <T> void save(T t) {
		this.getHibernateTemplate().save(t);
	}
	@Override
	public <T> void batchSave(Collection<T> collection){
		for(T t:collection){
			this.getHibernateTemplate().save(t);
		}
	}
	@Override
	public <T> void update(T t) {
		this.getHibernateTemplate().update(t);
	}
	@Override
	public <T> void batchUpdate(Collection<T> collection){
		for(T t:collection){
			this.getHibernateTemplate().update(t);
		}
	}
	@Override
	public <T> void delete(T t) {
		this.getHibernateTemplate().delete(t);
	}
	@Override
	public <T> void batchDelete(Collection<T> collection){
		for(T t:collection){
			this.getHibernateTemplate().delete(t);
		}
	}
	@Override
	public <T> T getById(Class<T> cls,Serializable id) {
		return this.getHibernateTemplate().get(cls, id);
	}
	
	@Override
	public <T> T loadById(Class<T> cls, Serializable id) {
		return this.getHibernateTemplate().load(cls, id);
	}
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> searchAllEntity(Class<T> cls) {
		return (List<T>)this.getHibernateTemplate().find("from "+cls.getName());
	}
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> searchEntity(Class<T> cls,DetachedCriteria criteria){
		return (List<T>)this.getHibernateTemplate().findByCriteria(criteria);
	}
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> searchEntity(String queryName,Class<T> cls,Object... paramValues){
		return (List<T>)this.getHibernateTemplate().findByNamedQuery(queryName, paramValues);
	}
	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> searchEntity(String queryName,Class<T> cls,String[] params,Object... paramValues){
		Session session = this.getSession();
		Query query = session.getNamedQuery(queryName);
		int length = params.length;
		for(int i=0;i<length;i++){
			query.setParameter(params[i], paramValues[i]);
		}
		return (List<T>)query.list();
	}
	@SuppressWarnings("unchecked")
	public <T> PageResult<T> getPageResult(String queryName,int pageSize, int currentPageNo,Object... parms){
		
		Query query = this.getSession().getNamedQuery(queryName);
		for(int i=0;i<parms.length;i++){
			query.setParameter(i, parms[i]);
		}
		long entityCount = getEntityCount(queryName,parms);
		int pageCount = (int)(entityCount%pageSize==0?entityCount/pageSize:entityCount/pageSize+1);
		int actualSize = 0;
		if(currentPageNo>=pageCount){
			currentPageNo = pageCount;
			actualSize = (int)(entityCount-(currentPageNo-1)*pageSize);
		}else{
			actualSize = pageSize;
		}
		query.setFirstResult((currentPageNo-1)*pageSize);
		query.setMaxResults(actualSize);
		class BasePageResult implements PageResult<T> {
			private long resultCount;
			private int firstPageNo=1;
			private int previousPageNo;
			private int currentPageNo;
			private int nextPageNo;
			private int lastPageNo;
			private int currentResultCount;
			private List<T> result;
			public BasePageResult(long resultCount,int lastPageNo,int currentPageNo,int currentResultCount,List<T> result){
				this.resultCount = resultCount;
				this.lastPageNo = lastPageNo;
				this.result = result;
				this.currentResultCount = currentResultCount;
				if(this.lastPageNo<=1){
					this.currentPageNo = 1;
					this.previousPageNo = 1;
					this.nextPageNo = 1;
					this.lastPageNo = 1;
				}else if(currentPageNo>=lastPageNo){
					this.currentPageNo = lastPageNo;
					this.previousPageNo = lastPageNo - 1;
					this.nextPageNo = lastPageNo;
				}else if(currentPageNo<=1){
					this.currentPageNo = 1;
					this.nextPageNo = 2;
					this.previousPageNo = 1;
				}else{
					this.currentPageNo = currentPageNo;
					this.nextPageNo = currentPageNo + 1;
					this.previousPageNo = currentPageNo - 1;
				}
			}
			
			@Override
			public long getResultCount() {
				return resultCount;
			}

			@Override
			public int getFirstPageNo() {
				return firstPageNo;
			}

			@Override
			public int getPreviousPageNo() {
				return previousPageNo;
			}

			@Override
			public int getCurrentPageNo() {
				return currentPageNo;
			}

			@Override
			public int getNextPageNo() {
				return nextPageNo;
			}

			@Override
			public int getLastPageNo() {
				return lastPageNo;
			}

			@Override
			public int getCurrentResultCount() {
				return currentResultCount;
			}

			@Override
			public List<T> getResult() {
				return this.result;
			}

			@Override
			public void setResult(List<T> result) {
				this.result = result;
			}

		}
		return new BasePageResult(entityCount, pageCount, currentPageNo, actualSize, (List<T>)query.list());
	}
	private long getEntityCount(String queryName,Object... parms){
		Query query = this.getSession().getNamedQuery(queryName+"Count");
		for(int i=0;i<parms.length;i++){
			query.setParameter(i, parms[i]);
		}
		long count = ((Long)query.uniqueResult()).longValue();
		return count;
	}
	@Override
	public void clearSession() {
		this.getHibernateTemplate().clear();
	}
	
}
